package com.example.miaosha.controller;

import com.example.miaosha.common.annotation.PassAnnotation;
import com.example.miaosha.common.enums.RedisEnums;
import com.example.miaosha.common.utils.IdWorkerUtil;
import com.example.miaosha.config.mq.MqProperties;
import com.example.miaosha.entity.SeUser;
import com.example.miaosha.entity.base.BaseResponse;
import com.example.miaosha.mapper.SeUserMapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Author jjtu
 * @Date 2021/12/27 19:44
 */
@Api("测试")
@RestController
public class TestController {

    @Resource
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private MqProperties mqProperties;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private SeUserMapper seUserMapper;
    @Resource
    private ExecutorService executorService;


    @GetMapping("/t")
    @PassAnnotation
    public BaseResponse test() {
        String seckillAct = RedisEnums.SECKILL_ACTIVITY + "123";
        List<String> keys = new ArrayList<>();
        keys.add(seckillAct);
        StringBuilder builder = new StringBuilder();
        // 4.1 判断是否存在该活动
        builder.append("if (redis.call('exists', KEYS[1]) == 1) then ");
        // 4.2 拿到库存
        builder.append("local stock = tonumber(redis.call('get',KEYS[1])); ");
        // 4.3 如果库存为 -1 就返回 1
        builder.append("if (stock == -1) then ");
        builder.append("return 1; ");
        builder.append("end; ");
////        // 4.4 如果还有库存就减一，并返回库存
        builder.append("if (stock > 0) then ");
        builder.append("redis.call('incrby',KEYS[1],-1) ");
        builder.append("return stock; ");
        builder.append("end; ");
////        // 4.5 如果库存小于0 则返回 0
//        builder.append("return 0; ");
        builder.append("end; ");
        builder.append("return -1; ");
        DefaultRedisScript<Long> defaultRedisScript = new DefaultRedisScript<>();
        defaultRedisScript.setScriptText(builder.toString());
//        defaultRedisScript.setScriptText("redis.call('incrby',KEYS[1],-1)");
        defaultRedisScript.setResultType(Long.class);
        Long stock = (Long) redisTemplate.execute(defaultRedisScript, keys, 11, TimeUnit.MILLISECONDS);
        System.out.println(stock);
//        defaultRedisScript.setScriptText("redis.call('set',KEYS[1],ARGV[1])");
//        redisTemplate.execute(defaultRedisScript, Collections.singletonList("tutu"),11, TimeUnit.MILLISECONDS);
        System.out.println();

        return BaseResponse.success(stock);
    }


    @GetMapping("/sendRabbitmq/{msg}")
    @PassAnnotation
    public BaseResponse sendMQ(@PathVariable("msg") String msg) {
        rabbitTemplate.convertAndSend(mqProperties.getDefaultExchange(),
                mqProperties.getRouteKey(), msg);
        return BaseResponse.SUCCESS;
    }


    @GetMapping("/testLock/{actID}")
    @PassAnnotation
    public BaseResponse testLock(@PathVariable("actID") String actID) {
        String key = RedisEnums.ACTIVITY_ID + actID;
        // 获取锁
        RLock lock = redissonClient.getLock(key);

        try {
            lock.lock();
        } catch (Exception e) {

        } finally {
            lock.unlock();
        }
        return BaseResponse.SUCCESS;
    }

    @ApiOperation("测试锁")
    @GetMapping("/addUser")
    public BaseResponse addUser() {
        executorService.submit(() -> {
            BigInteger phone = new BigInteger("15377302222");
            BigInteger item = new BigInteger("1");
            for (int i = 0; i < 1000; i++) {
                SeUser seUser = new SeUser();
                BigDecimal bigDecimal = BigDecimal.valueOf(10000);
                seUser.setMoney(bigDecimal);
                seUser.setId(IdWorkerUtil.nextId());
                seUser.setUserName("测试" + i);
                seUser.setPassWord("123");
                phone = phone.add(item);
                seUser.setPhone(String.valueOf(phone));
                seUserMapper.insert(seUser);
            }
        });
        return BaseResponse.SUCCESS;
    }
}
